package com.wsoft.core.utils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.read.builder.ExcelReaderBuilder;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.wsoft.annotation.ExcelFieldConvert;
import com.wsoft.constant.ExcelConstant;
import com.wsoft.constant.FieldConvertConstant;
import com.wsoft.core.service.IExcelDateService;
import com.wsoft.core.vo.*;
import com.wsoft.excel.config.ExcelRangeConfig;
import com.wsoft.excel.config.ExcelStyleConfig;
import com.wsoft.excel.config.ExcelWatermarkConfig;
import com.wsoft.excel.converter.DateConverter;
import com.wsoft.excel.converter.FieldDictConvert;
import com.wsoft.excel.converter.LocalDateTimeConverter;
import com.wsoft.excel.handler.ExcelMergeHandler;
import com.wsoft.excel.handler.ExcelStyleHandler;
import com.wsoft.excel.handler.ExcelWaterMarkHandler;
import com.wsoft.excel.listener.FormAnalysisEventListener;
import com.wsoft.excel.listener.GenericAnalysisEventListener;
import com.wsoft.service.IExcelFormDataService;
import kotlin.Triple;
import org.apache.poi.ss.util.CellRangeAddress;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.MediaTypeFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.util.*;

/**
 * Excel 数据 工具类
 *
 * @Author z001
 * @Date 2024/11/6 17:23
 */
@Component
public class ExcelDataUtil {

    /**
     * 静态变量存储数据库访问对象
     */
    static IExcelDateService excelDateService;


    static IExcelFormDataService excelFormDataService;

    @Resource
    public void setDatabaseService(IExcelDateService excelDateService) {
        ExcelDataUtil.excelDateService = excelDateService;
    }

    @Resource
    public void setDatabaseService(IExcelFormDataService excelFormDataService) {
        ExcelDataUtil.excelFormDataService = excelFormDataService;
    }

    /**
     * 数据库字典值
     */
    public static final Map<Triple<String, String, String>, Object> DATA_MAP = new HashMap<>();

    /**
     * 获取所有缓存数据
     *
     * @return
     */
    public static Map<Triple<String, String, String>, Object> getAllConvertData() {
        if (!DATA_MAP.isEmpty()) {
            return DATA_MAP;
        }
        //获取字典数据
        List<DictCacheVO> dictList = excelDateService.getDictAll();
        buildDictMap(dictList);
        //获取用户数据
        List<MemberVO> memberList = excelDateService.getUserAll();
        buildMemberMap(memberList);
        //获取组织数据
        List<OrganizationVO> orgList = excelDateService.getOrganizationAll();
        buildOrgMap(orgList);
        //获取岗位数据
        List<PostVO> postList = excelDateService.getPostAll();
        buildPostMap(postList);
        //获取职级数据
        List<LevelVO> levelList = excelDateService.getLevelAll();
        buildLevelMap(levelList);
        return DATA_MAP;
    }


    /**
     * 数据转换
     * @param list
     * @param clazz
     * @return
     * @param <T>
     * @throws Exception
     */
    public static <T> List<T> convertData(List<T> list, Class<T> clazz) throws Exception {
        getAllConvertData(clazz);

        List<T> resultList = new ArrayList<>();
        for (T obj : list) {
            T convertedObj = clazz.getDeclaredConstructor().newInstance();

            // 获取目标类的所有字段
            Field[] fields = clazz.getDeclaredFields();

            for (Field field : fields) {
                field.setAccessible(true);

                // 检查字段是否标注了 ExcelFieldConvert 注解
                ExcelFieldConvert annotation = field.getAnnotation(ExcelFieldConvert.class);
                if (annotation != null) {
                    // 获取源对象中对应字段的值
                    Field sourceField = obj.getClass().getDeclaredField(field.getName());
                    sourceField.setAccessible(true);
                    Object sourceValue = sourceField.get(obj);

                    String type = annotation.type();
                    String dictCode = annotation.dictCode();
                    // 进行数据字典转换
                    Object result = getResult(type, dictCode, sourceValue.toString());
                    field.set(convertedObj, result.toString());
                } else {
                    // 如果没有注解，直接复制字段值
                    Field sourceField = obj.getClass().getDeclaredField(field.getName());
                    sourceField.setAccessible(true);
                    Object sourceValue = sourceField.get(obj);
                    field.set(convertedObj, sourceValue);
                }
            }
            resultList.add(convertedObj);
        }
        return resultList;
    }

    /**
     * 获取转换的所有字典数据
     *
     * @return
     */
    public static <T> void getAllConvertData(Class<T> clazz) {
        List<String> typeList = convertToExcelData(clazz);
        if (CollUtil.isEmpty(typeList)) {
            return;
        }
        //获取字典数据
        if (typeList.contains(FieldConvertConstant.DICT)) {
            List<DictCacheVO> dictList = excelDateService.getDictAll();
            buildDictMap(dictList);
        }

        //获取用户数据
        if (typeList.contains(FieldConvertConstant.MEMBER)) {
            List<MemberVO> memberList = excelDateService.getUserAll();
            buildMemberMap(memberList);
        }

        //获取组织数据
        if (typeList.contains(FieldConvertConstant.ORGANIZATION)) {
            List<OrganizationVO> orgList = excelDateService.getOrganizationAll();
            buildOrgMap(orgList);
        }

        //获取岗位数据
        if (typeList.contains(FieldConvertConstant.POST)) {
            List<PostVO> postList = excelDateService.getPostAll();
            buildPostMap(postList);
        }

        //获取职级数据
        if (typeList.contains(FieldConvertConstant.LEVEL)) {
            List<LevelVO> levelList = excelDateService.getLevelAll();
            buildLevelMap(levelList);
        }
    }

    /**
     * 构建职级Map
     *
     * @param levelList
     */
    private static void buildLevelMap(List<LevelVO> levelList) {
        for (LevelVO vo : levelList) {
            DATA_MAP.put(new Triple<>(FieldConvertConstant.LEVEL, StrUtil.EMPTY, vo.getId().toString()), vo.getName());
            DATA_MAP.put(new Triple<>(FieldConvertConstant.LEVEL, StrUtil.EMPTY, vo.getName()), vo.getId());
        }
    }

    /**
     * 构建岗位Map
     *
     * @param postList
     */
    private static void buildPostMap(List<PostVO> postList) {
        for (PostVO vo : postList) {
            DATA_MAP.put(new Triple<>(FieldConvertConstant.POST, StrUtil.EMPTY, vo.getId().toString()), vo.getName());
            DATA_MAP.put(new Triple<>(FieldConvertConstant.POST, StrUtil.EMPTY, vo.getName()), vo.getId());
        }
    }

    /**
     * 构建orgMap
     *
     * @param orgList
     */
    private static void buildOrgMap(List<OrganizationVO> orgList) {
        for (OrganizationVO vo : orgList) {
            DATA_MAP.put(new Triple<>(FieldConvertConstant.ORGANIZATION, StrUtil.EMPTY, vo.getId().toString()), vo.getName());
            DATA_MAP.put(new Triple<>(FieldConvertConstant.ORGANIZATION, StrUtil.EMPTY, vo.getName()), vo.getId());
        }
    }

    /**
     * 构建memberMap
     *
     * @param memberList
     */
    private static void buildMemberMap(List<MemberVO> memberList) {
        for (MemberVO vo : memberList) {
            DATA_MAP.put(new Triple<>(FieldConvertConstant.MEMBER, StrUtil.EMPTY, vo.getId().toString()), vo.getName());
            DATA_MAP.put(new Triple<>(FieldConvertConstant.MEMBER, StrUtil.EMPTY, vo.getName()), vo.getId().toString());
        }
    }

    /**
     * 构建字典map
     *
     * @param dictList
     */
    private static void buildDictMap(List<DictCacheVO> dictList) {
        //组装map key是字典code,value是code对应的数据
        Map<String, List<DictDataCacheVO>> collect = new HashMap<>(16);
        for (DictCacheVO dictCacheVO : dictList) {
            collect.put(dictCacheVO.getCode(), dictCacheVO.getDataList());
        }

        Set<String> keySet = collect.keySet();
        for (String key : keySet) {
            List<DictDataCacheVO> dataVoList = collect.get(key);
            if(CollUtil.isEmpty(dataVoList)){
                continue;
            }
            for (DictDataCacheVO dictDataVo : dataVoList) {
                DATA_MAP.put(new Triple<>(FieldConvertConstant.DICT, key, dictDataVo.getCode()), dictDataVo.getName());
                DATA_MAP.put(new Triple<>(FieldConvertConstant.DICT, key, dictDataVo.getName()), dictDataVo.getCode());
            }
        }
    }


    /**
     * 从clazz中 获取 需要转换的类型
     *
     * @param clazz
     * @param <T>
     * @return
     */
    private static <T> List<String> convertToExcelData(Class<T> clazz) {
        List<String> typeList = new ArrayList<>();
        for (Field field : clazz.getDeclaredFields()) {
            field.setAccessible(true);
            //是否有注解
            if (field.isAnnotationPresent(ExcelFieldConvert.class)) {
                ExcelFieldConvert excelFieldConvertAnnotation = field.getAnnotation(ExcelFieldConvert.class);
                //注解type
                String type = excelFieldConvertAnnotation.type();
                typeList.add(type);
            }
        }
        return typeList;
    }


    /**
     * 设置通用消息头
     *
     * @param response
     * @param fileName
     */
    public static void setDownloadFileHeader(HttpServletResponse response, String fileName) {
        response.setCharacterEncoding("utf-8");
        try {
            if (StrUtil.isEmpty(fileName)) {
                fileName = ExcelConstant.DEFAULT_EXPORT_FILE_NAME;
            }
            response.setHeader(HttpHeaders.CONTENT_TYPE, MediaTypeFactory.getMediaType(fileName).orElse(MediaType.APPLICATION_OCTET_STREAM) + ";charset=utf-8");
            response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20"));
            response.setHeader(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, HttpHeaders.CONTENT_DISPOSITION);
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 不设置样式
     *
     * @return
     */
    public static WriteCellStyle setNullStyle() {
        return new WriteCellStyle();
    }

    /**
     * 构建excel 自定义样式
     *
     * @param config
     * @return
     */
    public static WriteCellStyle buildStyleHandler(ExcelStyleConfig config) {
        if (ObjUtil.isNull(config)) {
            return setNullStyle();
        }

        WriteCellStyle headWriteCellStyle = new WriteCellStyle();

        //设置字体
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontName(config.getFontName());
        headWriteFont.setFontHeightInPoints(config.getFontSize());
        headWriteFont.setBold(config.isBold());
        headWriteFont.setColor(config.getFontColor().index);
        headWriteCellStyle.setWriteFont(headWriteFont);

        //背景色
        if (null != config.getBackgroundColor()) {
            headWriteCellStyle.setFillForegroundColor(config.getBackgroundColor().index);
            headWriteCellStyle.setFillPatternType(config.getFillPattern());
        }

        //对齐方式
        headWriteCellStyle.setHorizontalAlignment(config.getHorizontalAlignment());
        headWriteCellStyle.setVerticalAlignment(config.getVerticalAlignment());

        //边框样式
        if (null != config.getBorder()) {
            headWriteCellStyle.setBorderBottom(config.getBorder());
            headWriteCellStyle.setBorderLeft(config.getBorder());
            headWriteCellStyle.setBorderRight(config.getBorder());
            headWriteCellStyle.setBorderTop(config.getBorder());
        } else {
            if (null != config.getBorderBottom()) {
                headWriteCellStyle.setBorderBottom(config.getBorderBottom());
            }
            if (null != config.getBorderLeft()) {
                headWriteCellStyle.setBorderLeft(config.getBorderLeft());
            }
            if (null != config.getBorderRight()) {
                headWriteCellStyle.setBorderRight(config.getBorderRight());
            }
            if (null != config.getBorderTop()) {
                headWriteCellStyle.setBorderTop(config.getBorderTop());
            }
        }

        //边框颜色
        if (null != config.getBorderColor()) {
            headWriteCellStyle.setBottomBorderColor(config.getBorderColor().getIndex());
            headWriteCellStyle.setLeftBorderColor(config.getBorderColor().getIndex());
            headWriteCellStyle.setRightBorderColor(config.getBorderColor().getIndex());
            headWriteCellStyle.setTopBorderColor(config.getBorderColor().getIndex());
        } else {
            if (null != config.getBottomBorderColor()) {
                headWriteCellStyle.setBottomBorderColor(config.getBottomBorderColor().getIndex());
            }
            if (null != config.getLeftBorderColor()) {
                headWriteCellStyle.setLeftBorderColor(config.getLeftBorderColor().getIndex());
            }
            if (null != config.getRightBorderColor()) {
                headWriteCellStyle.setRightBorderColor(config.getRightBorderColor().getIndex());
            }
            if (null != config.getTopBorderColor()) {
                headWriteCellStyle.setTopBorderColor(config.getTopBorderColor().getIndex());
            }
        }

        //是否自动换行
        headWriteCellStyle.setWrapped(config.isWrapText());

        //文本旋转角度
        headWriteCellStyle.setRotation(config.getRotation());

        return headWriteCellStyle;
    }


    /**
     * 构建 合并单元格
     *
     * @param rangeConfigList
     * @return
     */
    public static List<CellRangeAddress> buildCellRangeAddress(List<ExcelRangeConfig> rangeConfigList) {
        List<CellRangeAddress> rangeList = new ArrayList<>();
        if (CollUtil.isEmpty(rangeConfigList)) {
            return rangeList;
        }
        for (ExcelRangeConfig item : rangeConfigList) {
            rangeList.add(new CellRangeAddress(item.getFirstRow(), item.getLastRow(), item.getFirstCol(), item.getLastCol()));
        }
        return rangeList;
    }


    //################################# 导出 ########################################


    /**
     * 按指定目录导出
     */
    public static <T> void exportExcelFilePath(String filePath,
                                               String sheetName,
                                               List<T> data,
                                               Class<T> clazz,
                                               Set<String> includeColumnList,
                                               ExcelStyleConfig headStyle,
                                               ExcelStyleConfig contentStyle,
                                               List<ExcelRangeConfig> rangeConfigList,
                                               String waterMarkContent) {
        // 创建 ExcelWriter
        ExcelWriterBuilder writerBuilder = EasyExcel.write(filePath, clazz);
        exportExcelBase(writerBuilder, sheetName, data, clazz, includeColumnList, headStyle, contentStyle, rangeConfigList, waterMarkContent);
    }

    /**
     * 返回输出流
     *
     * @param outputStream
     * @param sheetName
     * @param data
     * @param clazz
     * @param includeColumnList
     * @param headStyle
     * @param contentStyle
     * @param rangeConfigList
     * @param waterMarkContent
     * @param <T>
     */
    public static <T> void exportExcelStream(ByteArrayOutputStream outputStream,
                                             String sheetName,
                                             List<T> data,
                                             Class<T> clazz,
                                             Set<String> includeColumnList,
                                             ExcelStyleConfig headStyle,
                                             ExcelStyleConfig contentStyle,
                                             List<ExcelRangeConfig> rangeConfigList,
                                             String waterMarkContent) {
        // 创建 ExcelWriter
        ExcelWriterBuilder writerBuilder = EasyExcel.write(outputStream, clazz);
        exportExcelBase(writerBuilder, sheetName, data, clazz, includeColumnList, headStyle, contentStyle, rangeConfigList, waterMarkContent);
    }

    public static <T> void exportExcelResponse(HttpServletResponse response,
                                               String fileName,
                                               String sheetName,
                                               List<T> data,
                                               Class<T> clazz,
                                               Set<String> includeColumnList,
                                               ExcelStyleConfig headStyle,
                                               ExcelStyleConfig contentStyle,
                                               List<ExcelRangeConfig> rangeConfigList,
                                               String waterMarkContent) throws IOException {
        //设置导出文件通用消息头
        setDownloadFileHeader(response, fileName);
        ExcelWriterBuilder write = EasyExcel.write(response.getOutputStream(), clazz);
        exportExcelBase(write, sheetName, data, clazz, includeColumnList, headStyle, contentStyle, rangeConfigList, waterMarkContent);
    }

    /**
     * Excel 导出方法
     *
     * @param writerBuilder     ExcelWriterBuilder
     * @param sheetName         指定sheet名
     * @param data              导出的数据
     * @param clazz             导出数据的类
     * @param includeColumnList 指定导出的列
     * @param headStyle         表头样式
     * @param contentStyle      内容样式
     * @param rangeConfigList   合并单元格
     * @param waterMarkContent  水印内容
     * @param <T>
     */
    private static <T> void exportExcelBase(ExcelWriterBuilder writerBuilder,
                                            String sheetName,
                                            List<T> data,
                                            Class<T> clazz,
                                            Set<String> includeColumnList,
                                            ExcelStyleConfig headStyle,
                                            ExcelStyleConfig contentStyle,
                                            List<ExcelRangeConfig> rangeConfigList,
                                            String waterMarkContent) {

        //获取转换所有数据
        ExcelDataUtil.getAllConvertData(clazz);
        //默认样式
        boolean useDefaultStyle = !ObjectUtil.isNotEmpty(headStyle);
        writerBuilder
                //自动调整列宽
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                //表头默认样式
                .useDefaultStyle(useDefaultStyle)
                //自定义表头样式
                .registerWriteHandler(new ExcelStyleHandler(ExcelDataUtil.buildStyleHandler(headStyle),
                        ExcelDataUtil.buildStyleHandler(contentStyle)))
                //合并单元格
                .registerWriteHandler(new ExcelMergeHandler(ExcelDataUtil.buildCellRangeAddress(rangeConfigList)))
                //水印
                .registerWriteHandler(new ExcelWaterMarkHandler(new ExcelWatermarkConfig(waterMarkContent)))
                //字典转换
                .registerConverter(new FieldDictConvert(ExcelDataUtil.DATA_MAP))
                //date转换
                .registerConverter(new DateConverter())
                //LocalDateTime转换
                .registerConverter(new LocalDateTimeConverter())
                //自定义列
                .includeColumnFieldNames(includeColumnList)
                //sheet页
                .sheet(StrUtil.isBlank(sheetName) ? ExcelConstant.DEFAULT_SHEET_NAME : sheetName)
                .doWrite(data);

    }

    //################################# 导入 ########################################

    /**
     * 导入excel
     *
     * @param inputStream 输入流
     * @param clazz       导入数据的类
     * @param sheetNo     sheetNo 从0开始
     * @param sheetName   sheetName
     * @param <T>
     * @return
     */
    public static <T> List<T> importExcelBase(InputStream inputStream, Class<T> clazz, Integer sheetNo, String sheetName) {
        //获取转换所有数据
        ExcelDataUtil.getAllConvertData(clazz);

        GenericAnalysisEventListener<T> listener = new GenericAnalysisEventListener<>(clazz, ExcelDataUtil.DATA_MAP);
        ExcelReaderBuilder builder = EasyExcel.read(inputStream, clazz, listener);
        if (StrUtil.isNotBlank(sheetName)) {
            builder.sheet(sheetName).doRead();
        } else {
            builder.sheet(null == sheetNo ? 0 : sheetNo).doRead();
        }
        return listener.getDataList();
    }


    //################################# form 自定义表单 ########################################


    /**
     * 导出模板
     *
     * @param response
     * @param fileName 导出文件名
     * @param designId 设计表id
     * @param parentId 父节点id (只导出子表时传,其余null)
     * @throws IOException
     */
    public static void exportFormTemplateResponse(HttpServletResponse response,
                                                  String fileName,
                                                  Long designId,
                                                  Long parentId,
                                                  ExcelStyleConfig headStyle,
                                                  List<ExcelRangeConfig> rangeConfigList,
                                                  String waterMarkContent) throws IOException {
        List<String> sheetNameList = new ArrayList<>();
        List<List<List<String>>> headList = new ArrayList<>();
        //构建表头
        buildExcelFormHeadInfo(designId, sheetNameList, headList, parentId);
        //多sheet导出
        exportMultiSheet(response, null, fileName, sheetNameList, headList, null, headStyle, null, rangeConfigList, waterMarkContent);

    }

    public static void exportFormTemplateStream(ByteArrayOutputStream outputStream,
                                                String fileName,
                                                Long designId,
                                                Long parentId,
                                                ExcelStyleConfig headStyle,
                                                List<ExcelRangeConfig> rangeConfigList,
                                                String waterMarkContent) throws IOException {
        List<String> sheetNameList = new ArrayList<>();
        List<List<List<String>>> headList = new ArrayList<>();
        //构建表头
        buildExcelFormHeadInfo(designId, sheetNameList, headList, parentId);
        //多sheet导出
        exportMultiSheet(null, outputStream, fileName, sheetNameList, headList, null, headStyle, null, rangeConfigList, waterMarkContent);

    }

    /**
     * 单Sheet页 数据导出
     * 用于 主表列表页导出
     * 子表列表页导出
     *
     * @param response
     * @param fileName
     * @param sheetName
     * @param headList
     * @param dataList
     * @throws IOException
     */
    public static void exportSingletonSheet(HttpServletResponse response,
                                            ByteArrayOutputStream outputStream,
                                            String fileName,
                                            String sheetName,
                                            List<List<String>> headList,
                                            List<List<String>> dataList,
                                            ExcelStyleConfig headStyle,
                                            ExcelStyleConfig contentStyle,
                                            List<ExcelRangeConfig> rangeConfigList,
                                            String waterMarkContent) throws IOException {

        ExcelWriter excelWriter = null;
        if (null == response) {
            excelWriter = EasyExcel.write(outputStream).build();
        } else {
            ExcelDataUtil.setDownloadFileHeader(response, fileName);
            excelWriter = EasyExcel.write(response.getOutputStream()).build();
        }

        //单个Sheet页
        exportSheetBase(excelWriter, sheetName, headList, dataList, null, headStyle, contentStyle, rangeConfigList, waterMarkContent);
        excelWriter.finish();
    }


    /**
     * 多sheet页 导出
     *
     * @param response
     * @param fileName
     * @param sheetNameList
     * @param headInfoList
     * @throws IOException
     */
    public static void exportMultiSheet(HttpServletResponse response,
                                        ByteArrayOutputStream outputStream,
                                        String fileName,
                                        List<String> sheetNameList,
                                        List<List<List<String>>> headInfoList,
                                        List<List<List<String>>> dataList,
                                        ExcelStyleConfig headStyle,
                                        ExcelStyleConfig contentStyle,
                                        List<ExcelRangeConfig> rangeConfigList,
                                        String waterMarkContent) throws IOException {

        ExcelWriter excelWriter = null;
        if (null == response) {
            excelWriter = EasyExcel.write(outputStream).build();
        } else {
            ExcelDataUtil.setDownloadFileHeader(response, fileName);
            excelWriter = EasyExcel.write(response.getOutputStream()).build();
        }

        for (int i = 0; i < sheetNameList.size(); i++) {
            String sheetName = sheetNameList.get(i);
            List<List<String>> headInfo = headInfoList.get(i);
            List<List<String>> data = new ArrayList<>();
            if (CollUtil.isNotEmpty(dataList)) {
                data = dataList.get(i);
            }
            //单个Sheet页
            exportSheetBase(excelWriter, sheetName, headInfo, data, null, headStyle, contentStyle, rangeConfigList, waterMarkContent);
        }
        excelWriter.finish();

    }


    /**
     * 一个sheet页导出
     *
     * @param excelWriter
     * @param sheetName
     * @param headInfo          二维数组,
     *                          List<List<String>> : 里面的List<String> 代表的是每一列,相同的会自动合并
     *                          headInfo.add(Arrays.asList("个人信息","姓名"));
     *                          headInfo.add(Arrays.asList("个人信息","年龄"));
     *                          headInfo.add(Arrays.asList("个人信息","性别"));
     *                          headInfo.add(Arrays.asList("家庭信息","家庭住址"));
     *                          headInfo.add(Arrays.asList("家庭信息","门牌号"));
     * @param data
     * @param includeColumnList
     * @param headStyle
     * @param contentStyle
     * @param rangeConfigList
     * @param waterMarkContent
     * @param <T>
     */
    private static <T> void exportSheetBase(ExcelWriter excelWriter,
                                            String sheetName,
                                            List<List<String>> headInfo,
                                            List<T> data,
                                            Set<String> includeColumnList,
                                            ExcelStyleConfig headStyle,
                                            ExcelStyleConfig contentStyle,
                                            List<ExcelRangeConfig> rangeConfigList,
                                            String waterMarkContent) {

        //默认样式
        boolean useDefaultStyle = !ObjectUtil.isNotEmpty(headStyle);

        WriteSheet writeSheet = EasyExcel.writerSheet(sheetName)
                //多sheet页 需要手动赋值表头 (可以使用二维数组,也可以使用xxx.class)
                .head(headInfo)
                //自动调整 列宽
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                //表头默认样式
                .useDefaultStyle(useDefaultStyle)
                //自定义表头样式
                .registerWriteHandler(new ExcelStyleHandler(ExcelDataUtil.buildStyleHandler(headStyle),
                        ExcelDataUtil.buildStyleHandler(contentStyle)))
                //合并单元格
                .registerWriteHandler(new ExcelMergeHandler(ExcelDataUtil.buildCellRangeAddress(rangeConfigList)))
                //水印
                .registerWriteHandler(new ExcelWaterMarkHandler(new ExcelWatermarkConfig(waterMarkContent)))
                //date转换
                .registerConverter(new DateConverter())
                //LocalDateTime转换
                .registerConverter(new LocalDateTimeConverter())
                //自定义列
                .includeColumnFieldNames(includeColumnList)

                .build();
        excelWriter.write(data, writeSheet);
    }


    /**
     * 构建 模板导出 多sheet页 表头参数
     *
     * @param designId      设计表id
     * @param sheetNameList sheet页名称集合
     * @param headList      表头信息集合
     * @param parentId      如果是单表导出,需要传入子表的父节点id
     */
    public static void buildExcelFormHeadInfo(Long designId,
                                              List<String> sheetNameList,
                                              List<List<List<String>>> headList,
                                              Long parentId) {
        excelFormDataService.getExportTemplateDate(designId, sheetNameList, headList, parentId);
    }

    /**
     * 模板导入
     *
     * @param designId    设计表id
     * @param inputStream
     * @return
     */
    public static List<Map<Integer, Map<String, Object>>> importFormExcel(Long designId, InputStream inputStream) {
        FormAnalysisEventListener listener = new FormAnalysisEventListener();

        ExcelReaderBuilder builder = EasyExcel.read(inputStream, listener);
        builder.doReadAll();
        //读取模板数据
        List<Map<Integer, Map<String, Object>>> resultList = listener.getResultList();

        //读取的父节点id
        String parentId = listener.getParentId();

        //解析模板数据
        ExcelDataUtil.importExcelFormData(designId, resultList, parentId);
        return resultList;
    }


    public static void buildExcelFormDataInfo() {
    }

    /**
     * 解析 Excel传上来的数据 并插入数据库
     *
     * @param designId
     * @param resultList
     */
    public static void importExcelFormData(Long designId, List<Map<Integer, Map<String, Object>>> resultList, String parentId) {
        excelFormDataService.importExcelFormData(designId, resultList, parentId);
    }

    /**
     * 从dataMap中获取值
     *
     * @param type
     * @param dictCode
     * @param value
     * @return
     */
    public static Object getResult(String type, String dictCode, String value) {
        return DATA_MAP.get(new Triple<>(type, dictCode, value)) == null ? value : DATA_MAP.get(new Triple<>(type, dictCode, value));
    }

}
